module ieee754_multi
(
    //data input
    input      [31:0] a,
    input      [31:0] b,
    
    //data output
    output  [31:0] c,
    output  reg   err             
);

// 指数域
wire [7:0] exp_a_raw = a[30:23];
wire [7:0] exp_b_raw = b[30:23];
// 判断非规格化数（指数为0）
wire a_denorm = (exp_a_raw == 8'd0);
wire b_denorm = (exp_b_raw == 8'd0);

// 尾数处理：非规格化数隐含0，规格化数隐含1
wire [23:0] abs_a = a_denorm ? {1'b0, a[22:0]} : {1'b1, a[22:0]};
wire [23:0] abs_b = b_denorm ? {1'b0, b[22:0]} : {1'b1, b[22:0]};

    // 指数调整：非规格化数实际指数为-126（按指数=1处理）
// 两个浮点数的指数域相加，可能会有进位，也可能会有借位，因此定义变量为10bit
wire [7:0] exp_a = (a_denorm ? 8'd1 : exp_a_raw);
wire [7:0] exp_b = (b_denorm ? 8'd1 : exp_b_raw);
//----------------------------------------------
wire sign_c;
wire    [8:0]   exp_c_2       ;
wire    [47:0]  abs_c_raw     ;
wire    [24:0]  abs_c_raw_2   ;

reg [7:0] exp_c;
reg [23:0] abs_c;

//----------------------------------------------
assign sign_c         = a[31] ^ b[31];
assign exp_c_2        = exp_a  + exp_b    ;  
assign abs_c_raw      = abs_a  * abs_b    ;
assign abs_c_raw_2    = abs_c_raw[47:23]    ;

//exp_c_2: 0~125   -> real exp: -254~-129 : [err] too little
//exp_c_2: 126~381 -> real exp: -128~127  : normal range      
//exp_c_2: 382~510 -> real exp: 128~256   : [err] too large      

//sepcial case:
//abs_c_raw_2[24]=0, real exp == -128, too little
//abs_c_raw_2[24]=1, real exp == -128, normal
//abs_c_raw_2[24]=0, real exp ==  127, normal
//abs_c_raw_2[24]=1, real exp ==  127, too large 

always @(*)
begin
    //-----------------------
    if (exp_c_2 <= 9'd125) //too little
    begin
        exp_c  = 8'h00;
        abs_c  = 24'h800000;
        err      = 1'b1;
    end

    //-----------------------
    else if (exp_c_2 == 9'd126) 
    begin
        if (abs_c_raw_2[24]) //normal
        begin
            exp_c  = 8'h00;
            abs_c  = abs_c_raw_2[24:1];
            err      = 1'b0;
        end
        else    //too little
        begin
            exp_c  = 8'h00;
            abs_c  = 24'h800000;
            err      = 1'b1;
        end
    end

    //-----------------------
    else if (exp_c_2 <= 9'd380) 
    begin
        if (abs_c_raw_2[24])  //too large 
        begin
            exp_c  = exp_c_2 - 9'd126;
            abs_c  = abs_c_raw_2[24:1];
            err      = 1'b0;
        end
        else // (abs_c_raw_2[23]), normal
        begin
            exp_c  = exp_c_2 - 9'd127;
            abs_c  = abs_c_raw_2[23:0];
            err      = 1'b0;
        end
    end

    //-----------------------
    else if (exp_c_2 == 9'd381) 
    begin
        if (abs_c_raw_2[24])    //too large
        begin
            exp_c  = 8'hff;
            abs_c  = 24'h800000;
            err      = 1'b1;
        end
        else  //(abs_c_raw_2[23]), normal, abs normal keep exp leagal
        begin
            exp_c  = 8'hfe;
            abs_c  = abs_c_raw_2[23:0];
            err      = 1'b0;
        end
    end

    //-----------------------
    else  // too large
    begin
        exp_c  = 8'hff;
        abs_c  = 24'h800000;
        err      = 1'b1;
    end
end
    
  assign c = {sign_c, exp_c, abs_c[22:0]};

endmodule